using CfgTable;
using Cinemachine;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using UnityEngine;
using IQIGame.Onigao.GameAOT;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// 俯视角相机控制类
    /// </summary>
    public abstract class QuarterViewCameraController : TCameraController
    {
        /// <summary>
        /// 切换场景相机时，相机变化的时长
        /// </summary>
        public const float SwitchTweenDuration = 1f;

        /// <summary>
        /// 备用角色相机
        /// </summary>
        protected CinemachineVirtualCamera vc_CharacterAlternative;
        /// <summary>
        /// 角色相机切换索引
        /// </summary>
        protected int _characterCameraIndex;
        /// <summary>
        /// 角色相机组件集合
        /// </summary>
        protected CinemachineVirtualCamera[] _vcCharCameras = new CinemachineVirtualCamera[2];
        protected CinemachinePOV[] _vcCharCameraPovs = new CinemachinePOV[2];
        protected CinemachineFramingTransposer[] _vcCharCameraBodys = new CinemachineFramingTransposer[2];
        /// <summary>
        /// 手动控制相机
        /// </summary>
        protected CinemachineVirtualCamera vc_CharacterMannual;
        /// <summary>
        /// 手动控制相机组件
        /// </summary>
        protected CinemachinePOV vcMannualPov;
        protected CinemachineFramingTransposer vcMannualBody;
        /// <summary>
        /// 相机配置id
        /// </summary>
        protected int? _cameraCid;

        /// <summary>
        /// 跟随主角的视角相机
        /// </summary>
        protected override CinemachineVirtualCamera vcCharCamera => _vcCharCameras[_characterCameraIndex];
        protected override CinemachinePOV vcCharCameraPov => _vcCharCameraPovs[_characterCameraIndex];
        protected override CinemachineFramingTransposer vcCharCameraBody => _vcCharCameraBodys[_characterCameraIndex];

        protected abstract int GetSceneDefaultCameraCid();

        protected override UniTask PreloadCamera()
        {
            var cameraRoot = GameObject.Find("CameraRoot");
            if (cameraRoot == null)
            {
                LogGame.LogError("Can't find CameraRoot.");
                return UniTask.CompletedTask;
            }
            cameraRootBinding = cameraRoot.GetComponent<ObjectBinding>();

            InitBinding(cameraRootBinding);

            //获取原生角色相机
            _vcCharCameras[0] = vc_Character;
            _vcCharCameraPovs[0] = vc_Character.GetCinemachineComponent<CinemachinePOV>();
            _vcCharCameraBodys[0] = vc_Character.GetCinemachineComponent<CinemachineFramingTransposer>();
            //创建备用角色相机
            vc_CharacterAlternative = vc_Character.gameObject.Instantiate(vc_Character.transform.parent).GetComponent<CinemachineVirtualCamera>();
            vc_CharacterAlternative.gameObject.SetActive(false);
            vc_CharacterAlternative.gameObject.name = "vc_Character_Alternative";
            _vcCharCameras[1] = vc_CharacterAlternative;
            _vcCharCameraPovs[1] = vc_CharacterAlternative.GetCinemachineComponent<CinemachinePOV>();
            _vcCharCameraBodys[1] = vc_CharacterAlternative.GetCinemachineComponent<CinemachineFramingTransposer>();

            //复制出来一个做为自由移动的virtual camera
            vc_CharacterMannual = vc_Character.gameObject.Instantiate(vc_Character.transform.parent).GetComponent<CinemachineVirtualCamera>();
            vc_CharacterMannual.gameObject.SetActive(false);
            vc_CharacterMannual.gameObject.name = "CameraMotion";

            //相机碰撞器，处理山体类碰撞
            var cameraCollider = vc_CharacterMannual.gameObject.AddComponent<CinemachineCollider>();
            cameraCollider.m_MinimumDistanceFromTarget = 1f;        // 相机与主角最小距离，太小就会和主角穿模
            cameraCollider.m_DistanceLimit = 3f;                    // 相机到主角之间的射线检测最大距离
            cameraCollider.m_Strategy = CinemachineCollider.ResolutionStrategy.PullCameraForward;

            //手动相机
            vcMannualPov = vc_CharacterMannual.GetCinemachineComponent<CinemachinePOV>();
            vcMannualBody = vc_CharacterMannual.GetCinemachineComponent<CinemachineFramingTransposer>();

            //动画相机
            vcMoveTargetPov = vc_MoveTarget.GetCinemachineComponent<CinemachinePOV>();
            vcMoveTargetBody = vc_MoveTarget.GetCinemachineComponent<CinemachineFramingTransposer>();

            //根据配置设置默认值
            int cameraCid = GetSceneDefaultCameraCid();
            if (cameraCid != 0)
            {
                CfgLevelCamera cfgLevelCamera = TableCenter.levelCamera.Get(cameraCid);
                _defaultCameraCharacterDistance = cfgLevelCamera.Distance.CentimetreToMetre();
                _defaultCameraCharacterRotate = new Vector2(cfgLevelCamera.XAngle, cfgLevelCamera.YAngle);
                _defaultCameraCharRotateMinMax = new Vector2(cfgLevelCamera.YAngleMin, cfgLevelCamera.YAngleMax);
            }
            else //如果完全找不到任何配置或保存数据，则使用预设上原生的参数
            {
                _defaultCameraCharacterDistance = vcCharCameraBody.m_CameraDistance;
                _defaultCameraCharacterRotate = new Vector2(vcCharCameraPov.m_VerticalAxis.Value, vcCharCameraPov.m_HorizontalAxis.Value);
                _defaultCameraCharRotateMinMax = new Vector2(vcCharCameraPov.m_HorizontalAxis.m_MinValue, vcCharCameraPov.m_HorizontalAxis.m_MaxValue);
            }

            //如果有保存数据，以保存数据为准
            int customCameraCid = GetSavedCameraCid();
            if (customCameraCid != 0) //如果有保存的玩家数据（策划自定义当前相机）
            {
                CfgLevelCamera cfgLevelCamera = TableCenter.levelCamera.Get(customCameraCid);
                _fixCameraCharacterDistance = cfgLevelCamera.Distance.CentimetreToMetre();
                _fixCameraCharacterRotate = new Vector2(cfgLevelCamera.XAngle, cfgLevelCamera.YAngle);
                _fixCameraCharRotateMinMax = new Vector2(cfgLevelCamera.YAngleMin, cfgLevelCamera.YAngleMax);
            }
            else
            {
                _fixCameraCharacterDistance = _defaultCameraCharacterDistance;
                _fixCameraCharacterRotate = _defaultCameraCharacterRotate;
                _fixCameraCharRotateMinMax = _defaultCameraCharRotateMinMax;
            }

            SetCharacterCameraParam(_fixCameraCharacterRotate, _fixCameraCharRotateMinMax, _fixCameraCharacterDistance);

            return UniTask.CompletedTask;
        }

        protected virtual int GetSavedCameraCid()
        {
            return 0;
        }

        public override void CharacterFllowLook(Transform follow, Transform lookat)
        {
            this.vc_CharacterAlternative.Follow = follow;
            this.vc_CharacterAlternative.LookAt = lookat;
            this.vc_CharacterMannual.Follow = follow;
            this.vc_CharacterMannual.LookAt = lookat;

            base.CharacterFllowLook(follow, lookat);
        }

        protected void SetCharacterCameraParam(Vector2 axisValue, Vector2 yAngleMinMax, float distance)
        {
            //设置参数到当前角色相机（有两个角色虚拟相机，用于切换时的缓动）
            vcCharCameraBody.m_CameraDistance = distance;
            SetPOV(vcCharCameraPov, axisValue, yAngleMinMax);
            //设置镜头动画虚拟相机，和角色跟随相机匹配
            vcMoveTargetBody.m_CameraDistance = distance;
            SetPOV(vcMoveTargetPov, axisValue, yAngleMinMax);
        }

        protected override void RotateCamera(Vector2 delta)
        {
            vcMannualPov.m_HorizontalAxis.Value += delta.x * VcamRotateFactor;
        }

        protected override void SwitchToManaulVirtualCamera()
        {
            this.vc_CharacterMannual.gameObject.SetActive(true);
            this.vcCharCamera.gameObject.SetActive(false);

            vc_CharacterMannual.transform.position = vcCharCameraPov.transform.position;
            vcMannualBody.m_CameraDistance = _fixCameraCharacterDistance;
            SetPOV(vcMannualPov, _fixCameraCharacterRotate, _fixCameraCharRotateMinMax);
        }

        /// <summary>
        /// 退出手动操作相机
        /// </summary>
        protected override void ExitCameraOperation()
        {
            this.vc_CharacterMannual.gameObject.SetActive(false);
            this.vcCharCamera.gameObject.SetActive(true);
            base.ExitCameraOperation();
        }

        #region 默认相机修改
        /// <summary>
        /// 离开区域还原相机
        /// </summary>
        public void RecoverCameraAfterExitArea()
        {
            this._cameraCid = null;
            ResetCharacterCameraToDefault();
        }

        /// <summary>
        /// 改变跟随角色的相机
        /// </summary>
        /// <param name="cameraCid"></param>
        public void ChangeCharacterCamera(int cameraCid)
        {
            this._cameraCid = cameraCid;
            if (cameraCid == 0)
            {
                return;
            }

            var cameraCfg = TableCenter.levelCamera.Get(cameraCid);
            if (cameraCfg == null)
            {
                return;
            }

            _fixCameraCharacterDistance = cameraCfg.Distance.CentimetreToMetre();
            _fixCameraCharacterRotate = new Vector2(cameraCfg.XAngle, cameraCfg.YAngle);
            _fixCameraCharRotateMinMax = new Vector2(cameraCfg.YAngleMin, cameraCfg.YAngleMax);

            SwitchAndSetCharacterCamera(_fixCameraCharacterRotate, _fixCameraCharRotateMinMax, _fixCameraCharacterDistance);
        }

        /// <summary>
        /// 将角色相机还原到当前场景的默认值（在区域中以区域为标准，不在区域中以地区默认相机为标准）
        /// </summary>
        public void ResetCharacterCamera()
        {
            if (_cameraCid != null)
            {
                ChangeCharacterCamera(_cameraCid.Value);
            }
            else
            {
                ResetCharacterCameraToDefault();
            }
        }

        /// <summary>
        /// 将角色相机还原到默认值
        /// </summary>
        private void ResetCharacterCameraToDefault()
        {
            _fixCameraCharacterDistance = _defaultCameraCharacterDistance;
            _fixCameraCharacterRotate = _defaultCameraCharacterRotate;
            _fixCameraCharRotateMinMax = _defaultCameraCharRotateMinMax;

            SwitchAndSetCharacterCamera(_fixCameraCharacterRotate, _fixCameraCharRotateMinMax, _fixCameraCharacterDistance);
        }

        /// <summary>
        /// 切换角色相机并为新相机设置参数（两个备用相机之间切换，利用virtualCamera的切换缓动效果）
        /// </summary>
        /// <param name="axisValue"></param>
        /// <param name="distance"></param>
        private void SwitchAndSetCharacterCamera(Vector2 axisValue, Vector2 yAngleMinMax, float distance)
        {
            cinemachineBrain.m_DefaultBlend.m_Time = SwitchTweenDuration;
            //隐藏旧相机
            vcCharCameraPov.transform.parent.gameObject.SetActive(false);
            //切换（_characterCameraIndex改变后，vcCharCameraBody等属性取值会变为新相机）
            _characterCameraIndex = (_characterCameraIndex + 1) % _vcCharCameraPovs.Length;
            //设置参数（到切换后的新相机）
            SetCharacterCameraParam(axisValue, yAngleMinMax, distance);
            //显示新相机
            vcCharCameraPov.transform.parent.gameObject.SetActive(true);
        }
        #endregion
    }
}
